Modernize and bring up to date with JS pixelmatch#8
Open
Conversation
kkaefer
reviewed
Apr 30, 2026
| {"7a", "7b", 0.1}, | ||
| }; | ||
|
|
||
| using clock = std::chrono::steady_clock; |
Member
There was a problem hiding this comment.
We could use Google Benchmark for more precise timing
Member
Author
There was a problem hiding this comment.
Yes, but I think it's fine to have less precise numbers — +-5% noise here isn't critical since it's a testing library, but simpler approach can reliably detect substantial gains like 3x, and we keep the repo simple, no submodules / vendored files.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Build system
INTERFACElibrary,mapbox::pixelmatchalias, install rules for downstreamfind_package).deps/gyp/,deps/run_gyp,pixelmatch.gyp, the wrapperMakefile, and.travis.yml..clang-formatenforcement in CI viaclang-format --dry-run --Werror.Tests
pngjsconvert_tests.jsstep and the committed*.rgbablobs.checkerboard: falseto match our white-blend semantics).Algorithm port (from JS pixelmatch)
Brought the implementation up to date with ~10 years of upstream improvements, while deliberately keeping:
alpha/aaColor/diffColor/diffColorAlt/diffMask).Performance changes
memcmpshort-circuits the entire loop when both inputs are byte-equal.colorDelta, so identical pixels skip all YIQ math.colorDeltarewrite — operates on raw channel diffs and only blends with white when α<255. The opaque case (the common one) now skips the blend math entirely. Mathematically equivalent to the old white-blend formula.antialiasedrewrite:zeroesinitialization fix (treats off-image neighbors as implicit zeroes, matching upstream behavior).antialiased(...)for the sibling-confirmation step replaced with a much simplerhasManySiblingsdoing raw RGBA equality viamemcmp. This was the biggest single win.antialiasedandhasManySiblings(closes a latent bug where the AA path assumed tightly-packed input even when called via the stride overload).Correctness changes
drawGrayPixelnow reads from img1 with the stride-aware offset (was using the tightly-packed output offset, broken for stride ≠ width × 4).zeroes=1initialization fixes a small over-flagging on image borders. This is what changes the4a vs 4bcount from 36089 → 36049 (40 pixels at edges previously misclassified as differences).Benchmark results
Added a
bench_pixelmatchexecutable that runs the full fixture set with auto-calibrated iteration counts.